package com.eternal.base.data;

import com.eternal.base.concat.DeviceMinModel;
import com.eternal.base.concat.DeviceModel;
import com.eternal.base.concat.DeviceModelInfo;
import com.eternal.base.data.ble.BleStatue;
import com.eternal.base.data.ble.IBleControl;
import com.eternal.base.data.source.INotificationSource;
import com.eternal.base.database.entity.Notification;

import java.util.List;

import io.reactivex.Single;
import io.reactivex.SingleEmitter;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.SingleSource;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public class NotificationRepository extends BaseRepository {
    INotificationSource source;

    public NotificationRepository(INotificationSource source, IBleControl control) {
        super(control);
        this.source = source;
    }

    public Single<DeviceModelInfo> getModelInfo(final String mac) {
        return Single.create(new SingleOnSubscribe<DeviceModelInfo>() {
            @Override
            public void subscribe(SingleEmitter<DeviceModelInfo> emitter) throws Exception {
                emitter.onSuccess(source.getModelInfo(mac));
            }
        });
    }

    public Single<List<Notification>> getNotifications(final String mac, final byte port) {
        return Single.create(new SingleOnSubscribe<List<Notification>>() {
            @Override
            public void subscribe(SingleEmitter<List<Notification>> emitter) throws Exception {
                emitter.onSuccess(source.getNotifications(mac, port));
            }
        });
    }

    public Single<List<Notification>> getNotifications(BleStatue statue, byte port) {
        return control.getNotifications(statue, port);
    }

    public Single<List<Notification>> getNotifications(BleStatue statue) {
        return control.getNotifications(statue);
    }

    public Single<Boolean> openNotification(BleStatue statue, final Notification notification) {
        return control.setNotification(statue, notification, true, notification.open)
                .subscribeOn(Schedulers.io()).observeOn(Schedulers.io())
                .doOnSuccess(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) {
                        if (aBoolean) {
                            source.setNotificationOpen(notification.mac, notification.port, notification.id, notification.type, notification.open);
                        }
                    }
                });
    }

    public Single<Boolean> removeNotification(BleStatue statue, final Notification notification) {
        return control.setNotification(statue, notification, false, false)
                .subscribeOn(Schedulers.io()).observeOn(Schedulers.io())
                .doOnSuccess(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean result) throws Exception {
                        if (result) {
                            source.deleteNotification(notification.mac, notification.port, notification.id, notification.type);
                        }
                    }
                });
    }

    public Single<Boolean> nameIsExists(final String mac, final byte port, final String name) {
        return Single.create(new SingleOnSubscribe<Boolean>() {
            @Override
            public void subscribe(SingleEmitter<Boolean> emitter) throws Exception {
                emitter.onSuccess(source.nameExists(mac, port, name));
            }
        });
    }

    public Single<Boolean> saveNotification(final BleStatue statue, final Notification notification) {
        return Single.create(new SingleOnSubscribe<Notification>() {
            @Override
            public void subscribe(SingleEmitter<Notification> emitter) throws Exception {
                source.create(notification);
                emitter.onSuccess(notification);
            }
        }).flatMap(new Function<Notification, SingleSource<? extends Boolean>>() {
            @Override
            public SingleSource<? extends Boolean> apply(Notification notification) throws Exception {
                return control.setNotification(statue, notification, true, true);
            }
        }).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).doOnSuccess(new Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean) throws Exception {
                if (aBoolean) {
                    source.addNotification(notification);
                }
            }
        });
    }

    public Single<Boolean> setNotification(BleStatue statue, final Notification notification) {
        return control.setNotification(statue, notification, true, notification.open)
                .subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).doOnSuccess(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean result) throws Exception {
                        if (result) {
                            source.setNotification(notification);
                        }
                    }
                });
    }
}
